#ifndef SPEED_CNTR_H
#define SPEED_CNTR_H

#include "freq_table.h"
#include "global.h"
#include "freq_table.h"

struct SpeedRampData;

typedef void (*SPEED_CALLBACK)();
typedef void (*STEP_UPDATE)();
typedef void (*PULSE_PROC)(uchar level);
typedef void (*TIMER_PROC)(ushort tick);
typedef void (*STOP_TIMER)();

typedef struct SpeedRampData
{
    uchar run_state : 3;        // What part of the speed ramp we are in.
    uchar dir : 1;              // Direction stepper motor should move.
    uchar running : 1;          // 电机正在运行
    uchar need_cleanup : 1;     // 需要运行清除函数
    uchar home_state : 1;       // 原点传感器状态
    uchar limit_state : 1;      // 限位传感器状态
    uchar hit_home : 1;         // 运行经过原点
    uchar ignore_step_left : 1; // 碰到原点时不重新计算剩余步数
    uchar coder_self : 1;       // 脉冲计数方式 0：编码器计数 1：定时器自身计数

    uchar micro;                // 当前电机细分, 为0时表示使用默认16细分
    ushort speed_index;         // Counter used when accelerateing/decelerateing to calculate step_delay.
    ushort max_index;           // 频率表最大索引
    long step_left;             // 电机剩余运行步数
    ulong step_count;           // Counting steps when moving.
    ulong start_time;           // 开始运行时间
    int step_offset;           // 每走一步的增量, +/-1
    long target;                // 目标坐标
    ushort first_stage_speed;   // 开始阶段低速运行的速度索引
    ushort first_stage_step;    // 开始阶段低速运行的步数
    ushort second_stage_speed;  // 结束阶段低速运行的速度索引
    ushort second_stage_step;   // 结束阶段低速运行的步数
    uchar micro_step;           // 细分脉冲计步步数


    SPEED_CALLBACK init;        // 电机启动前调用的初始化函数
    SPEED_CALLBACK update;      // 每走一步调用的函数
    SPEED_CALLBACK cleanup;     // 停止后调用的函数
    PULSE_PROC step;            // step信号输出
    TIMER_PROC start_timer;     // 更新定时器
    STOP_TIMER stop_timer;      // 停止定时器
} SpeedRampData;

// Speed ramp states
#define MOTION_STATE_STOP       0
#define MOTION_STATE_ACCEL      1
#define MOTION_STATE_DECEL      2
#define MOTION_STATE_RUN        3

#define CCW                     0   // 反向
#define CW                      1   // 正向

extern SpeedRampData srd_x;
extern SpeedRampData srd_y;
extern SpeedRampData srd_z;
extern SpeedRampData srd_m;

ushort speed_cntr_max_index(ushort speed);
void speed_cntr_Move(SpeedRampData *srd, long step, unsigned int speed);
void speed_cntr_update(SpeedRampData *srd);
void speed_cntr_interp(long xstep, long ystep, unsigned int speed);
void speed_cntr_interp_update(void);
#endif

